package main

import "fmt"

/*
1.接口中可以定义一组方法,但不需要实现,不需要方法体.并且接口中不能包含任何变量
到某个自定义类型需要使用的时候(实现接口的时候),再根据具体情况把这些方法具体实现出来
2.实现接口要实现所有的方法才是实现
3.golang中实现接口是基于方法的,不是基于接口的(golang中没有implement关键字)
例如:
A接口: a,b方法
B接口: a,b方法
C结构体实现了 a,b方法, 那么C实现了A接口,也可以说实现了B接口
只要实现全部方法即可,和实际接口的耦合性很低,比java松散得多
4.接口目的是为了定义规范,具体由别人来实现即可
*/

/*
1.接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量
2.只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
3.一个自定义类型可以实现多个接口
4.一个接口(比如A接口)可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法全部实现
5.interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用那么会输出nil
6.空接口没有任何方法,所以可以认为所有类型都实现了空接口,也可以理解为我们可以把任何一个变量赋值给空接口
*/

//接口的定义: 定义规则,定义规范,定义某种能力
type SayHello interface {
	//声明没有具体实现的方法
	sayHello()
}

//接口的实现: 定义一个结构体
type Chinese struct {
}

func (c Chinese) sayHello() {
	fmt.Println("你好")
}

//接口的实现: 定义一个结构体
type American struct {
}

func (a American) sayHello() {
	fmt.Println("hello")
}

//定义一个函数,专门用来各国人打招呼的函数,接收具备 SayHello 接口能力的变量
//多态参数 s, 可以接收 SayHello 类型所有参数`
func greet(s SayHello) {
	s.sayHello()
}

type integer int

func (i integer) sayHello() {
	//只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
	fmt.Println("我是int类型,say=", i)
}

func main() {
	c := &Chinese{}
	a := American{}
	greet(c)
	greet(a)

	fmt.Println("---------------- ---------------- ----------------")

	//直接用接口创建实例,会报错
	//var s SayHello
	//s.sayHello()

	//可以使用接口具体的实现
	var s SayHello = Chinese{}
	s.sayHello()

	fmt.Println("---------------- ---------------- ----------------")

	var i integer = 10
	var s2 SayHello = i
	s2.sayHello()

	fmt.Println("---------------- ---------------- ----------------")

	//多态数组
	var arr [2]SayHello
	arr[0] = American{}
	arr[1] = Chinese{}

	fmt.Println(arr)

}
